package x.trident.core.config.center.processor;

import com.alibaba.nacos.api.exception.NacosException;
import lombok.NonNull;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.stereotype.Component;
import x.trident.core.config.center.annotation.TridentConfig;
import x.trident.core.config.center.inject.InjectFunc;
import x.trident.core.config.center.manager.ConfigManager;

import javax.annotation.Resource;
import java.lang.reflect.Field;


/**
 * 注入配置项的处理单元
 *
 * @author 林选伟
 * @date 2021/9/3 5:36 下午
 */
@Slf4j
@Component
public class TridentConfigProcessor implements BeanPostProcessor {
    @Resource
    private ConfigManager configManager;

    @Resource
    private InjectFunc injectFunc;

    @SneakyThrows
    @Override
    public Object postProcessBeforeInitialization(Object bean, @NonNull String beanName) {
        Class<?> clazz = bean.getClass();
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            processField(bean, field);
        }
        return bean;
    }

    /**
     * 从配置中心获取配置值，并注入对应的field
     *
     * @param bean  当前bean
     * @param field bean里的字段
     * @throws NacosException 异常
     */
    private void processField(Object bean, Field field) throws NacosException {
        TridentConfig tridentConfig = AnnotationUtils.getAnnotation(field, TridentConfig.class);

        if (tridentConfig == null) {
            return;
        }

        String dataId = tridentConfig.value();
        Object value = configManager.getValue(dataId);
        configManager.addListener(dataId, injectFunc, bean, field);
        if (value == null) {
            return;
        }
        injectFunc.inject(bean, field, value);
    }

}


